package com.wjq.demo.hystrix;

import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.HystrixCommandProperties;

import java.sql.Time;
import java.time.LocalDateTime;
import java.util.concurrent.TimeUnit;

import static com.wjq.demo.hystrix.RxJavaTest.log;


/**
 * @author wjq
 * @since 2023-04-21
 */
public class CircuitBreakerTest extends HystrixCommand<String> {


    public static void main(String[] args) throws InterruptedException {
        CircuitBreakerTest circuitBreakerTest = null;
        System.out.println(LocalDateTime.now().toString()+"first execute。。。。。。。。");
        log(LocalDateTime.now().toString());
        long start = System.currentTimeMillis();
        for (int i = 0; i < 20; i++) {
            circuitBreakerTest = new CircuitBreakerTest();
            circuitBreakerTest.userId = i;
            String r = circuitBreakerTest.execute();
            System.out.println(r);
        }

        long end = System.currentTimeMillis();

        log("execute time:" + (end - start));

        boolean open = circuitBreakerTest.circuitBreaker.isOpen();
        log(LocalDateTime.now().toString()+"before 500ms the circuit breaker status:" + open);


        TimeUnit.MILLISECONDS.sleep(1000 - (end - start));
        open = circuitBreakerTest.circuitBreaker.isOpen();
        log(LocalDateTime.now().toString()+"after 1000ms  the circuit breaker status:" + open);


        Thread.sleep(1000);
        open = circuitBreakerTest.circuitBreaker.isOpen();
        System.out.println("2.the circuit breaker status:" + open);
        Thread.sleep(1000);
        open = circuitBreakerTest.circuitBreaker.isOpen();
        System.out.println("3.the circuit breaker status:" + open);
        Thread.sleep(1000);
        open = circuitBreakerTest.circuitBreaker.isOpen();
        System.out.println("4.the circuit breaker status:" + open);
        Thread.sleep(1000);
        open = circuitBreakerTest.circuitBreaker.isOpen();
        System.out.println("5.the circuit breaker status:" + open);
        Thread.sleep(1000);

        System.out.println("second execute。。。。。。。。");

        open = circuitBreakerTest.circuitBreaker.isOpen();
        System.out.println("the circuit breaker status:" + open);

        for (int i = 0; i < 10; i++) {
            circuitBreakerTest = new CircuitBreakerTest();
            circuitBreakerTest.userId = i;
            String r = circuitBreakerTest.execute();
            System.out.println(r);
        }

        Thread.sleep(5000);
        System.out.println("third execute。。。。。。。。");

        for (int i = 0; i < 10; i++) {
            circuitBreakerTest = new CircuitBreakerTest();
            circuitBreakerTest.userId = i;
            String r = circuitBreakerTest.execute();
            System.out.println(r);
        }
    }

    private final OrderServiceProvider orderServiceProvider = new OrderServiceProvider();

    public CircuitBreakerTest() {
        super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("CircuitBreaker"))
                .andCommandPropertiesDefaults(HystrixCommandProperties.defaultSetter()
                        .withCircuitBreakerRequestVolumeThreshold(10)
                        .withMetricsRollingStatisticalWindowInMilliseconds(5000)));
    }


    private int userId;

    @Override
    protected String run() {
        return orderServiceProvider.queryByOrderId(userId);
    }


    @Override
    protected String getFallback() {
        return "fall back it ！！！";
    }

    static class OrderServiceProvider {
        public String queryByOrderId(Integer id) {
            System.out.println("the circuit breaker not open");
            if (id % 2 == 0) {
                throw new RuntimeException("service exception！！！");
            } else {
                return "用户" + id;
            }

        }
    }
}
